package com.tyk.demo.aspect;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo;
import com.tyk.demo.service.DataDictValueService;
import com.tyk.demo.utils.LocalDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;

@Aspect
@Component
@Slf4j
public class DictAspect {
    private static final String DICT_TEXT_SUFFIX = "TranslateText";
    private static final Logger LOGGER = LoggerFactory.getLogger(DictAspect.class);
    @Autowired
    private DataDictValueService dataDictValueService;

    @Pointcut("execution (* com.tyk.demo.controller.*.*(..))")
    public void executeService() {

    }

    @Around("executeService()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        LocalDateTime start = LocalDateTime.now();
        Object result = joinPoint.proceed();
        LocalDateTime end = LocalDateTime.now();
        LOGGER.info("获取json数据耗时{}ms", Duration.between(start,end).toMillis());

        LocalDateTime start1 = LocalDateTime.now();
        // 转换
        parseDictText(result);
        LocalDateTime end1 = LocalDateTime.now();
        LOGGER.info("解析数据耗时{}ms", Duration.between(start1, end1).toMillis());
        return result;
    }

    private void parseDictText(Object result) {
        if (result instanceof PageInfo) {
            List<JSONObject> items = new ArrayList<>();
            PageInfo pageInfo = (PageInfo) result;
            items = new ArrayList<>();
            for (Object record:pageInfo.getList()) {
                ObjectMapper mapper = new ObjectMapper();
                // 序列化LocalDateTime
//                JavaTimeModule module = new JavaTimeModule();
//                module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
//                mapper.registerModule(module);
                String json = "{}";
                try {
                    json = mapper.writeValueAsString(record);
                } catch (JsonProcessingException e) {
                    LOGGER.error("JSON数据解析失败！！！", e);
                    e.printStackTrace();
                }

                JSONObject item = JSONObject.parseObject(json);
                for (Field field : record.getClass().getDeclaredFields()) {
                    if (field.getAnnotation(Dict.class) != null) {
                        String typeId = field.getAnnotation(Dict.class).typeId();
                        String text = field.getAnnotation(Dict.class).text();

                        String code = String.valueOf(item.get(field.getName()));
                        String textValue = translateDictValue(typeId, code);
                        LOGGER.debug("字典val：{}", textValue);
                        LOGGER.debug("翻译字典字段：{}", field.getName() + DICT_TEXT_SUFFIX + textValue);
                        if (StringUtils.isNotBlank(text)) {
                            item.put(text, textValue);
                        } else {
                            item.put(field.getName() + DICT_TEXT_SUFFIX, textValue);
                        }
                    }
                    if (field.getType().getName().equals("java.time.LocalDateTime")) {
                        long timestamp = Long.parseLong(item.get(field.getName()).toString());
                        LocalDateTime dateTime = Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
                        item.put(field.getName(), LocalDateUtil.localDateTime2String(dateTime,null));
                    }
                }
                items.add(item);
            }
            pageInfo.setList(items);
        }
    }

    private String translateDictValue(String typeId, String code) {
        if (StringUtils.isBlank(code)) {
            return null;
        }
        return dataDictValueService.findByTypeIdAndCode(typeId, code);
    }
}
